package com.laolang.shop.modules.product.logic.admin.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.laolang.shop.common.core.domain.Page;
import com.laolang.shop.common.core.util.AssertUtil;
import com.laolang.shop.common.core.util.CommonUtil;
import com.laolang.shop.modules.product.consts.admin.ProductCategoryConst;
import com.laolang.shop.modules.product.entity.ProductCategory;
import com.laolang.shop.modules.product.logic.admin.ProductCategoryAdminLogic;
import com.laolang.shop.modules.product.mapperstruct.ProductCategoryMapperStruct;
import com.laolang.shop.modules.product.pojo.category.admin.dto.ProductCategoryAdminEditDto;
import com.laolang.shop.modules.product.pojo.category.admin.vo.ProductCategoryAdminTreeVo;
import com.laolang.shop.modules.product.service.ProductCategoryService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author khlbat
 * @version 1.0
 * @date 2020/11/3 0:58
 */
@Slf4j
@AllArgsConstructor
@Service
public class ProductCategoryAdminLogicImpl implements ProductCategoryAdminLogic {

    private final ProductCategoryService productCategoryService;

    private final ProductCategoryMapperStruct productCategoryMapperStruct;


    @Override
    public List<ProductCategoryAdminTreeVo> loadTreeLazy(Long parentId) {
        return productCategoryService.listByParentId(parentId);
    }

    @Override
    public Page<ProductCategory> page(Integer page, Integer size, Long parentId) {
        return CommonUtil.pageInfo2Page(productCategoryService.page(page, size,
                Wrappers.<ProductCategory>lambdaQuery()
                        .eq(ProductCategory::getParentId, parentId)
                        .orderByAsc(ProductCategory::getSort)
                        .orderByAsc(ProductCategory::getCreateTime)
                )
        );
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean add(ProductCategoryAdminEditDto dto) {
        beforeEditCheck(dto, true);
        productCategoryService.save(productCategoryMapperStruct.adminEditDto2entity(dto));
        return afterEdit();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean edit(ProductCategoryAdminEditDto dto) {
        checkEntityExist(dto.getId());
        beforeEditCheck(dto, false);
        productCategoryService.updateById(productCategoryMapperStruct.adminEditDto2entity(dto));
        return afterEdit();
    }

    /**
     * 编辑前的数据有效性检查
     */
    private void beforeEditCheck(ProductCategoryAdminEditDto dto, boolean checkName) {
        AssertUtil.isTrue(CommonUtil.enumHasValue(ProductCategoryConst.Status.class, dto.getStatus()), "分类状态不正确");
        // 父 id 不存在则默认为 0
        if (null == dto.getParentId()) {
            dto.setParentId(0L);
        }
        // 不可添加四级及以上分类
        int level = 1;
        Long pid = dto.getParentId();
        while (level <= 4) {
            ProductCategory parent = productCategoryService.getById(pid);
            if (null == parent) {
                break;
            } else {
                pid = parent.getParentId();
                level++;
            }
        }
        AssertUtil.isTrue(level < 4, "不可添加四级及以上分类");
        // 名称不能为空
        AssertUtil.isTrue(StrUtil.isNotBlank(dto.getName()), "商品分类名称不能为空");
        // 重置排序

        if (null == dto.getSort()) {
            int count = productCategoryService.count(
                    Wrappers.<ProductCategory>lambdaQuery()
                            .eq(ProductCategory::getParentId, dto.getParentId())
            );
            dto.setSort(0 == count ? 1 : count + 1);
        } else {
            int count = productCategoryService.count(
                    Wrappers.<ProductCategory>lambdaQuery()
                            .eq(ProductCategory::getParentId, dto.getParentId())
                            .eq(ProductCategory::getSort, dto.getSort())
            );
            if (0 != count) {
                ProductCategory one = productCategoryService.getOne(Wrappers.<ProductCategory>lambdaQuery()
                        .eq(ProductCategory::getParentId, dto.getParentId())
                        .orderByDesc(ProductCategory::getSort)
                );
                dto.setSort(one.getSort() + 1);
            }
        }

        // 在同一父分类下不能有同名子分类
        if (checkName) {
            AssertUtil.isTrue(
                    0 == productCategoryService.count(
                            Wrappers.<ProductCategory>lambdaQuery()
                                    .eq(ProductCategory::getName, dto.getName())
                                    .eq(ProductCategory::getParentId, dto.getParentId())
                    ),
                    StrUtil.format("父分类下已有名称为: {} 的分类", dto.getName())
            );
        }
    }


    /**
     * 修改商品分类最后修改时间
     */
    private boolean afterEdit() {
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean del(Long id) {
        ProductCategory entity = checkEntityExist(id);
        // 有子分类的不能删除
        AssertUtil.isTrue(
                0 == productCategoryService.count(
                        Wrappers.<ProductCategory>lambdaQuery()
                                .eq(ProductCategory::getParentId, id)
                ),
                StrUtil.format("分类: {} 还有子分类", entity.getName())
        );
        return productCategoryService.removeById(id);
    }

    /**
     * 检查分类是否在数据库中
     *
     * @param id id
     * @return entity
     */
    private ProductCategory checkEntityExist(Long id) {
        ProductCategory entity = productCategoryService.getById(id);
        AssertUtil.notNull(entity, "分类信息不存在");
        return entity;
    }
}
